package com.sunseaypw.console;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;

import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.Lifecycle;
import org.springframework.context.SmartLifecycle;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.stereotype.Controller;

public class SpringAbout2 {
    public static void main( String[] args ){
        ClassPathXmlApplicationContext ctx=new ClassPathXmlApplicationContext("application666.xml");
        CycleA ca=(CycleA)ctx.getBean("cycleA");
        ca.selfIntruduce();
        CycleB cb=(CycleB)ctx.getBean("cycleB");
        cb.selfIntruduce();

        // CycleA ca111=(CycleA)ctx.getBean("cycleA111");
        // ca111.introduceB();
        // CycleB cb111=(CycleB)ctx.getBean("cycleB111");
        // cb111.introduceA();

        CycleA ca888=(CycleA)ctx.getBean("cycleA888");   
        //接口工厂bean的实例
        Product p = (Product)ctx.getBean("productFactory");
        p.showMe();
        //静态工厂bean的实例
        Product p222 = (Product)ctx.getBean("productFactory222");
        p222.showMe();
        //实例工厂bean的实例
        Product p444= (Product)ctx.getBean("productFactory444");
        p444.showMe();

        MyProtoType mp =(MyProtoType)ctx.getBean("myProtoType");
        /* 只有显示调用start/stop才能对只实现了Lifecycle接口的bean进行传播start/stop事件！！
           对于实现了SmartLifecycle接口的bean，则在context onfresh时会自动级联触发其下此类bean的start
        */
        ctx.start();
        ctx.stop();
        //可触发destroy/@PreDestroy 但会间接触发stop事件，如果isRunning=true的话
        ctx.registerShutdownHook();
        try{
            Thread.sleep(1000);
        }catch(Exception ex){

        }
    }
    public static class BeanWithAsyn implements Lifecycle{
        private volatile boolean isRunning = false;
         /**
         * 检查此组件是否正在运行。
         * 1. 只有该方法返回false时，start方法才会被执行。
         * 2. 只有该方法返回true时，stop(Runnable callback)或stop()方法才会被执行。
         */
        public boolean isRunning(){
            System.out.println("BeanWithAsyn的isRunning被调用了啊");
            return isRunning;
        }
        public void start(){
            System.out.println("BeanWithAsyn的start被调用了啊");
            isRunning=true;
        }
        public void stop(){
            System.out.println("BeanWithAsyn的stop被调用了啊");
            isRunning=false;
        }
        
    }
    public static class BeanWithAsyn222 implements SmartLifecycle{
         /**
         * 如果该`Lifecycle`类所在的上下文在调用`refresh`时,希望能够自己自动进行回调，则返回`true`* ,
         * false的值表明组件打算通过显式的start()调用来启动，类似于普通的Lifecycle实现。
         */
        @Override
        public boolean isAutoStartup() {
            return true;
        }
        private volatile boolean isRunning = false;
         /**
         * 检查此组件是否正在运行。
         * 1. 只有该方法返回false时，start方法才会被执行。
         * 2. 只有该方法返回true时，stop(Runnable callback)或stop()方法才会被执行。
         */
        public boolean isRunning(){
            System.out.println("BeanWithAsyn2222222222222的isRunning被调用了啊");
            return isRunning;
        }
        public void start(){
            System.out.println("BeanWithAsyn2222222222222的start被调用了啊");
            isRunning=true;
        }
        /** 优先调用 */
        public void stop(Runnable callback) {
            System.out.println("BeanWithAsyn2222222 stop runnable 容器停止...");
            stop();
            callback.run();
        }
        public void stop(){
            System.out.println("BeanWithAsyn22222222222222的stop被调用了啊");
            isRunning=false;
        }
        
    }

    public static class CycleA{  
        public String title;
        public CycleA(String title){
            System.out.println("我是CycleA 正在被初始化构造:"+title); 
            this.title=title;
        }    
        public void selfIntruduce(){
          System.out.println("我是CycleA 我的title是:"+this.title);  
        }
        //set注入
        private CycleB myB;
        public void setCycleB(CycleB myB){
            System.out.println("CycleA的setCycleB被注入了");
            this.myB=myB;
        }
        //构造注入
        private CycleB myB000;   
        public CycleA(CycleB myB){
            this.title="我是构造注入的CycleAAAAAAA";
            this.myB000=myB;
        }           
        public void introduceB(){
            System.out.println("构造注入进来的CycleB："+this.myB000.title);
        }

        //多重构造注入           
        public CycleA(java.lang.Integer count){
            this.title="我是多重构造注入的CycleAAAAAAA:::::"+count.intValue();  
            System.out.println(this.title);           
        }   

        //xml用属性注入后，注解又注入，则注解就是postprocessor会覆盖之前的注入信息
        @Autowired
        public void setMySchool(String school){
            System.out.println("setMySchool我被注入了："+school);   
        } 

        @PostConstruct
        public void init(){
            System.out.println("CycleA的 @PostConstruct init() 被触发了");   
        }

        @PreDestroy
        public void close(){
            System.out.println("CycleA的 @PreDestroy close() 被触发了");   
        }
    }
    public static class CycleB{
        public String title;
        public CycleB(String title){
            this.title=title;
        }        
        public void selfIntruduce(){
          System.out.println("我是CycleB 我的title是:"+this.title);  
        }
        //set注入
        private CycleA myA;
        public void setCycleA(CycleA myA){
            System.out.println("CycleB的setCycleA被注入了");
            this.myA=myA;
        }
        //构造注入
        private CycleA myA000;   
        public CycleB(CycleA myA){
            this.title="我是构造注入的CycleBBBBBBB";
            this.myA000=myA;
        }           
        public void introduceA(){
            System.out.println("构造注入进来的CycleA："+this.myA000.title);
        }
    }

    @Controller
    public static class MyExample{ 
        //自动扫描时，根据构造方法的参数类型进行自动匹配bean并注入
        //若匹配出多个，则异常，需要用qualifier进行指定即可       
        public MyExample(@Qualifier("cycleA888") CycleA ca){
            System.out.println("MyExample:我被构造注入了");            
        }
        
        CycleA ca;
        @Autowired  //自动装配的涵义是由容器在实例化过程中，自动匹配参数并执行方法！若是字段则自动匹配后直接赋值！
        @Qualifier("cycleA")
        public void setName(CycleA ca){
            System.out.println("MyExample:我被set注入了");
            this.ca=ca;
        }
    }

    @Controller    
    public static class MyExample222{ 
        public MyExample222(){
            System.out.println("MyExample222:我被构造注入了"); 
        }
    }
        
    public static class MyFactoryBean implements FactoryBean<Product>{        
        public Product getObject() throws java.lang.Exception{
            return new Product("有一个啊");
        }
        public java.lang.Class<?> getObjectType(){
            return Product.class;
        }
        public boolean isSingleton(){
            return false;
        }
    }
    public static class Product{
        private String title;
        public Product(String title){
            System.out.println("工厂bean的产品Product被构造了::::"+title);
            this.title=title;
        }
        public void showMe(){
            System.out.println("Product展示自我:::"+title);
        }
        public void setHello(String hello){
            System.out.println("Product的hello被注入触发了:::"+hello);
        }

        @PreDestroy
        public void close(){
            System.out.println("Product的@PreDestroy close方法被触发了，所属title:::"+this.title);
        }
    }
    //不实现FactoryBean接口，由xml配置触发
    public static class MyFactoryBean222{
        public static Product getProduct(){
            return new Product("非工厂接口的xml配置而构建 静态方法 static 出生的！！");
        }
    }
    //不实现FactoryBean接口，由xml配置触发
    public static class MyFactoryBean333{
        public Product getProduct(){
            return new Product("非工厂接口的xml配置而构建 实例方法 object 出生的！！");
        }
    }

    //纯prototype模式的bean验证其生命周期托管情况
    public static class MyProtoType{
        public MyProtoType(){
            System.out.println("MyProtoType 被注册实例化了啊");
        }
        @PostConstruct
        public void init(){
            System.out.println("MyProtoType的@PostConstruct init方法被触发了");
        }
        
        public void init111(){
            System.out.println("MyProtoType的init1111方法被触发了");
        }

        @PreDestroy
        public void close(){
            System.out.println("MyProtoType的@PreDestroy close方法被触发了");
        }
    }

    //纯Singleton模式的bean验证其生命周期托管情况
    public static class MySingleton{
        public MySingleton(){
            System.out.println("MySingleton 被注册实例化了啊");
        }
        
        @PreDestroy
        public void close(){
            System.out.println("MySingleton的@PreDestroy close方法被触发了");
        }

        public void close111(){
            System.out.println("MySingleton的close1111方法被触发了");
        }
    }
}
